home *** CD-ROM | disk | FTP | other *** search
/ 3D GFX / 3D GFX.iso / amiutils / i_l / irit5 / cagd_lib / cbzr_aux.c < prev    next >
C/C++ Source or Header  |  1995-12-30  |  24KB  |  596 lines

  1. /******************************************************************************
  2. * CBzr-Aux.c - Bezier curve auxilary routines.                      *
  3. *******************************************************************************
  4. * Written by Gershon Elber, Mar. 90.                          *
  5. ******************************************************************************/
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include "cagd_loc.h"
  11.  
  12. /*****************************************************************************
  13. * DESCRIPTION:                                                               M
  14. * Given a Bezier curve - subdivides it into two sub-curves at the given      M
  15. * parametric value.                                                          M
  16. *   Returns pointer to first curve in a list of two subdivided curves.       M
  17. *                                                                            *
  18. * PARAMETERS:                                                                M
  19. *   Crv:       To subdivide at parametr value t.                             M
  20. *   t:         Parameter value to subdivide Crv at.                          M
  21. *                                                                            *
  22. * RETURN VALUE:                                                              M
  23. *   CagdCrvStruct *:  A list of the two subdivided curves.                   M
  24. *                                                                            *
  25. * KEYWORDS:                                                                  M
  26. *   BzrCrvSubdivAtParam, subdivision, refinement                             M
  27. *****************************************************************************/
  28. CagdCrvStruct *BzrCrvSubdivAtParam(CagdCrvStruct *Crv, CagdRType t)
  29. {
  30.     CagdBType
  31.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  32.     int i, j, l,
  33.     k = Crv -> Length,
  34.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  35.     CagdRType
  36.     t1 = 1.0 - t;
  37.     CagdCrvStruct *LCrv, *RCrv;
  38.  
  39.     if (t < 0.0 || t > 1.0)
  40.     CAGD_FATAL_ERROR(CAGD_ERR_T_NOT_IN_CRV);
  41.  
  42.     LCrv = BzrCrvNew(k, Crv -> PType);
  43.     RCrv = BzrCrvNew(k, Crv -> PType);
  44.  
  45.     /* Copy Curve into RCrv, so we can apply the recursive algo. to it.      */
  46.     for (i = 0; i < k; i++)
  47.     for (j = IsNotRational; j <= MaxCoord; j++)
  48.         RCrv -> Points[j][i] = Crv -> Points[j][i];
  49.  
  50.     for (j = IsNotRational; j <= MaxCoord; j++)
  51.     LCrv -> Points[j][0] = Crv -> Points[j][0];
  52.  
  53.     /* Apply the recursive algorithm to RCrv, and update LCrv with the         */
  54.     /* temporary results. Note we updated the first point of LCrv above.     */
  55.     for (i = 1; i < k; i++) {
  56.     for (l = 0; l < k - i; l++)
  57.         for (j = IsNotRational; j <= MaxCoord; j++)
  58.         RCrv -> Points[j][l] = RCrv -> Points[j][l] * t1 +
  59.                      RCrv -> Points[j][l+1] * t;
  60.     /* Copy temporary result to LCrv: */
  61.     for (j = IsNotRational; j <= MaxCoord; j++)
  62.         LCrv -> Points[j][i] = RCrv -> Points[j][0];
  63.     }
  64.     LCrv -> Pnext = RCrv;
  65.  
  66.     return LCrv;
  67. }
  68.  
  69. /*****************************************************************************
  70. * DESCRIPTION:                                                               M
  71. * Returns a new curve, identical to the original but with order N.         M
  72. *   Degree raise is computed by multiplying by a constant 1 curve of order   M
  73. *                                                                            *
  74. * PARAMETERS:                                                                M
  75. *   Crv:        To raise its degree to a NewOrder.                           M
  76. *   NewOrder:   NewOrder for Crv.                                            M
  77. *                                                                            *
  78. * RETURN VALUE:                                                              M
  79. *   CagdCrvStruct *:  A curve of order NewOrder representing the same        M
  80. *                     geometry as Crv.                                       M
  81. *                                                                            *
  82. * KEYWORDS:                                                                  M
  83. *   BzrCrvDegreeRaiseN, degree raising                                       M
  84. *****************************************************************************/
  85. CagdCrvStruct *BzrCrvDegreeRaiseN(CagdCrvStruct *Crv, int NewOrder)
  86. {
  87.     int i, j, RaisedOrder,
  88.     Order = Crv -> Order,
  89.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  90.     CagdCrvStruct *RaisedCrv, *UnitCrv;
  91.  
  92.     if (NewOrder < Order) {
  93.     CAGD_FATAL_ERROR(CAGD_ERR_WRONG_ORDER);
  94.     return NULL;
  95.     }
  96.     RaisedOrder = NewOrder - Order + 1;
  97.  
  98.     UnitCrv = BzrCrvNew(RaisedOrder, CAGD_MAKE_PT_TYPE(FALSE, MaxCoord));
  99.     for (i = 1; i <= MaxCoord; i++)
  100.     for (j = 0; j < RaisedOrder; j++)
  101.         UnitCrv -> Points[i][j] = 1.0;
  102.  
  103.     RaisedCrv = BzrCrvMult(Crv, UnitCrv);
  104.  
  105.     CagdCrvFree(UnitCrv);
  106.  
  107.     return RaisedCrv;
  108. }
  109.  
  110. /*****************************************************************************
  111. * DESCRIPTION:                                                               M
  112. * Returns a new curve, identical to the original but with one degree higher. M
  113. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:   M
  114. *               i        k-i                         V
  115. * Q(0) = P(0), Q(i) = --- P(i-1) + (---) P(i), Q(k) = P(k-1).             V
  116. *               k         k                         V
  117. *                                                                            *
  118. * PARAMETERS:                                                                M
  119. *   Crv:        To raise it degree by one.                                   M
  120. *                                                                            *
  121. * RETURN VALUE:                                                              M
  122. *   CagdCrvStruct *:  A curve of one order higher representing the same      M
  123. *                     geometry as Crv.                                       M
  124. *                                                                            *
  125. * KEYWORDS:                                                                  M
  126. *   BzrCrvDegreeRaise, degree raising                                        M
  127. *****************************************************************************/
  128. CagdCrvStruct *BzrCrvDegreeRaise(CagdCrvStruct *Crv)
  129. {
  130.     CagdBType
  131.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  132.     int i, j,
  133.     k = Crv -> Length,
  134.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  135.     CagdCrvStruct
  136.     *RaisedCrv = BzrCrvNew(k + 1, Crv -> PType);
  137.  
  138.     for (j = IsNotRational; j <= MaxCoord; j++)                /* Q(0). */
  139.     RaisedCrv -> Points[j][0] = Crv -> Points[j][0];
  140.  
  141.     for (i = 1; i < k; i++)                        /* Q(i). */
  142.     for (j = IsNotRational; j <= MaxCoord; j++)
  143.         RaisedCrv -> Points[j][i] =
  144.         Crv -> Points[j][i-1] * (i / ((CagdRType) k)) +
  145.         Crv -> Points[j][i] * ((k - i) / ((CagdRType) k));
  146.  
  147.     for (j = IsNotRational; j <= MaxCoord; j++)                /* Q(k). */
  148.     RaisedCrv -> Points[j][k] = Crv -> Points[j][k-1];
  149.  
  150.     return RaisedCrv;
  151. }
  152.  
  153. /*****************************************************************************
  154. * DESCRIPTION:                                                               M
  155. * Returns a unit vector, equal to the tangent to Crv at parameter value t.   M
  156. *   Algorithm: pseudo subdivide Crv at t and using control point of          M
  157. * subdivided curve find the tangent as the difference of the 2 end points.   M
  158. *                                                                            *
  159. * PARAMETERS:                                                                M
  160. *   Crv:       Crv for which to compute a unit tangent.                      M
  161. *   t:         The parameter at which to compute the unit tangent.           M
  162. *                                                                            *
  163. * RETURN VALUE:                                                              M
  164. *   CagdVecStruct *:  A pointer to a static vector holding the tangent       M
  165. *                     information.                                           M
  166. *                                                                            *
  167. * KEYWORDS:                                                                  M
  168. *   BzrCrvTangent, tangent                                                   M
  169. *****************************************************************************/
  170. CagdVecStruct *BzrCrvTangent(CagdCrvStruct *Crv, CagdRType t)
  171. {
  172.     static CagdVecStruct P2;
  173.     CagdVecStruct P1, *T;
  174.     CagdBType
  175.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  176.     int i, j, l,
  177.     k = Crv -> Length,
  178.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  179.     CagdRType
  180.     t1 = 1.0 - t;
  181.     CagdCrvStruct *RCrv;
  182.  
  183.     if (APX_EQ(t, 0.0)) {
  184.     /* Use Crv starting tangent direction. */
  185.     CagdCoerceToE3(P1.Vec, Crv -> Points, 0, Crv -> PType);
  186.     CagdCoerceToE3(P2.Vec, Crv -> Points, 1, Crv -> PType);
  187.     }
  188.     else if (APX_EQ(t, 1.0)) {
  189.     /* Use Crv ending tangent direction. */
  190.     CagdCoerceToE3(P1.Vec, Crv -> Points, k - 2, Crv -> PType);
  191.     CagdCoerceToE3(P2.Vec, Crv -> Points, k - 1, Crv -> PType);
  192.     }
  193.     else {
  194.     if (t < 0.0 || t > 1.0)
  195.         CAGD_FATAL_ERROR(CAGD_ERR_T_NOT_IN_CRV);
  196.  
  197.     RCrv = BzrCrvNew(k, Crv -> PType);
  198.  
  199.     /* Copy Crv into RCrv, so we can apply the recursive algo. to it. */
  200.     for (i = 0; i < k; i++)
  201.         for (j = IsNotRational; j <= MaxCoord; j++)
  202.         RCrv -> Points[j][i] = Crv -> Points[j][i];
  203.  
  204.     /* Apply the recursive algorithm to RCrv. */
  205.     for (i = 1; i < k; i++)
  206.         for (l = 0; l < k - i; l++)
  207.         for (j = IsNotRational; j <= MaxCoord; j++)
  208.             RCrv -> Points[j][l] = RCrv -> Points[j][l] * t1 +
  209.                        RCrv -> Points[j][l+1] * t;
  210.  
  211.     CagdCoerceToE3(P1.Vec, RCrv -> Points, 0, RCrv -> PType);
  212.     CagdCoerceToE3(P2.Vec, RCrv -> Points, 1, RCrv -> PType);
  213.  
  214.     CagdCrvFree(RCrv);
  215.     }
  216.  
  217.     CAGD_SUB_VECTOR(P2, P1);
  218.  
  219.     if (CAGD_LEN_VECTOR(P2) < IRIT_EPSILON) {
  220.     if (AttrGetIntAttrib(Crv -> Attr, "_tan") != TRUE) {
  221.         /* Try to move a little. This location has zero speed. However,  */
  222.         /* do it only once since we can be here forever. The "_tan"      */
  223.         /* attribute guarantee we will try to move EPSILON only once.    */
  224.         AttrSetIntAttrib(&Crv -> Attr, "_tan", TRUE);
  225.  
  226.         T = BzrCrvTangent(Crv, t < 0.5 ? t + EPSILON : t - EPSILON);
  227.  
  228.         AttrFreeOneAttribute(&Crv -> Attr, "_tan");
  229.  
  230.         return T;
  231.     }
  232.     else {
  233.         /* A zero length vector signals failure to compute tangent. */
  234.         return &P2;
  235.     }
  236.     }
  237.     else {
  238.     CAGD_NORMALIZE_VECTOR(P2);            /* Normalize the vector. */
  239.  
  240.     return &P2;
  241.     }
  242. }
  243.  
  244. /*****************************************************************************
  245. * DESCRIPTION:                                                               M
  246. * Returns a unit vector, equal to the binormal to Crv at parameter value t.  M
  247. *   Algorithm: insert (order - 1) knots and using 3 consecutive control      M
  248. * points at the refined location (p1, p2, p3), compute to binormal to be the M
  249. * cross product of the two vectors (p1 - p2) and (p2 - p3).             M
  250. *   Since a curve may have not BiNormal at inflection points or if the 3     M
  251. * points are colinear, NULL will be returned at such cases.             M
  252. *                                                                            *
  253. * PARAMETERS:                                                                M
  254. *   Crv:       Crv for which to compute a unit binormal.                     M
  255. *   t:         The parameter at which to compute the unit binormal.          M
  256. *                                                                            *
  257. * RETURN VALUE:                                                              M
  258. *   CagdVecStruct *:  A pointer to a static vector holding the binormal      M
  259. *                     information.                                           M
  260. *                                                                            *
  261. * KEYWORDS:                                                                  M
  262. *   BzrCrvBiNormal, binormal                                                 M
  263. *****************************************************************************/
  264. CagdVecStruct *BzrCrvBiNormal(CagdCrvStruct *Crv, CagdRType t)
  265. {
  266.     static CagdVecStruct P3;
  267.     CagdVecStruct P1, P2;
  268.     CagdBType
  269.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  270.     int i, j, l,
  271.     k = Crv -> Length,
  272.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  273.     CagdRType
  274.     t1 = 1.0 - t;
  275.     CagdCrvStruct *RCrv;
  276.  
  277.     /* Can not compute for linear curves. */
  278.     if (k <= 2)
  279.     return NULL;
  280.  
  281.     /* For planar curves, B is trivially the Z axis. */
  282.     if (CAGD_NUM_OF_PT_COORD(Crv -> PType) == 2) {
  283.     P3.Vec[0] = P3.Vec[1] = 0.0;
  284.     P3.Vec[2] = 1.0;
  285.     return &P3;
  286.     }
  287.  
  288.     if (APX_EQ(t, 0.0)) {
  289.     /* Use Crv starting tangent direction. */
  290.     CagdCoerceToE3(P1.Vec, Crv -> Points, 0, Crv -> PType);
  291.     CagdCoerceToE3(P2.Vec, Crv -> Points, 1, Crv -> PType);
  292.     CagdCoerceToE3(P3.Vec, Crv -> Points, 2, Crv -> PType);
  293.     }
  294.     else if (APX_EQ(t, 1.0)) {
  295.     /* Use Crv ending tangent direction. */
  296.     CagdCoerceToE3(P1.Vec, Crv -> Points, k - 3, Crv -> PType);
  297.     CagdCoerceToE3(P2.Vec, Crv -> Points, k - 2, Crv -> PType);
  298.     CagdCoerceToE3(P3.Vec, Crv -> Points, k - 1, Crv -> PType);
  299.     }
  300.     else {
  301.     if (t < 0.0 || t > 1.0)
  302.         CAGD_FATAL_ERROR(CAGD_ERR_T_NOT_IN_CRV);
  303.  
  304.     RCrv = BzrCrvNew(k, Crv -> PType);
  305.  
  306.     /* Copy Crv into RCrv, so we can apply the recursive algo. to it. */
  307.     for (i = 0; i < k; i++)
  308.         for (j = IsNotRational; j <= MaxCoord; j++)
  309.         RCrv -> Points[j][i] = Crv -> Points[j][i];
  310.  
  311.     /* Apply the recursive algorithm to RCrv. */
  312.     for (i = 1; i < k; i++)
  313.         for (l = 0; l < k - i; l++)
  314.         for (j = IsNotRational; j <= MaxCoord; j++)
  315.             RCrv -> Points[j][l] = RCrv -> Points[j][l] * t1 +
  316.                        RCrv -> Points[j][l+1] * t;
  317.  
  318.     CagdCoerceToE3(P1.Vec, RCrv -> Points, 0, RCrv -> PType);
  319.     CagdCoerceToE3(P2.Vec, RCrv -> Points, 1, RCrv -> PType);
  320.     CagdCoerceToE3(P3.Vec, RCrv -> Points, 2, RCrv -> PType);
  321.  
  322.     CagdCrvFree(RCrv);
  323.     }
  324.  
  325.     CAGD_SUB_VECTOR(P1, P2);
  326.     CAGD_SUB_VECTOR(P2, P3);
  327.  
  328.     CROSS_PROD(P3.Vec, P1.Vec, P2.Vec);
  329.  
  330.     if ((t = CAGD_LEN_VECTOR(P3)) < IRIT_EPSILON)
  331.     return NULL;
  332.     else
  333.     CAGD_DIV_VECTOR(P3, t);                /* Normalize the vector. */
  334.  
  335.     return &P3;
  336. }
  337.  
  338.  
  339. /*****************************************************************************
  340. * DESCRIPTION:                                                               M
  341. * Returns a unit vector, equal to the normal of Crv at parameter value t.    M
  342. *   Algorithm: returns the cross product of the curve tangent and binormal.  M
  343. *                                                                            *
  344. * PARAMETERS:                                                                M
  345. *   Crv:       Crv for which to compute a unit normal.                       M
  346. *   t:         The parameter at which to compute the unit normal.            M
  347. *                                                                            *
  348. * RETURN VALUE:                                                              M
  349. *   CagdVecStruct *:  A pointer to a static vector holding the normal        M
  350. *                     information.                                           M
  351. *                                                                            *
  352. * KEYWORDS:                                                                  M
  353. *   BzrCrvNoraml, normal                                                     M
  354. *****************************************************************************/
  355. CagdVecStruct *BzrCrvNormal(CagdCrvStruct *Crv, CagdRType t)
  356. {
  357.     static CagdVecStruct N, *T, *B;
  358.  
  359.     T = BzrCrvTangent(Crv, t);
  360.     B = BzrCrvBiNormal(Crv, t);
  361.  
  362.     if (T == NULL || B == NULL)
  363.     return NULL;
  364.  
  365.     CROSS_PROD(N.Vec, T -> Vec, B -> Vec);
  366.  
  367.     CAGD_NORMALIZE_VECTOR(N);                /* Normalize the vector. */
  368.  
  369.     return &N;
  370. }
  371.  
  372. /*****************************************************************************
  373. * DESCRIPTION:                                                               M
  374. * Returns a new curve, equal to the given curve, differentiated once.        M
  375. * Let old control polygon be P(i), i = 0 to k-1, and Q(i) be new one then:   M
  376. * Q(i) = (k - 1) * (P(i+1) - P(i)), i = 0 to k-2.                 M
  377. *                                                                            *
  378. * PARAMETERS:                                                                M
  379. *   Crv:        To differentiate.                                            M
  380. *                                                                            *
  381. * RETURN VALUE:                                                              M
  382. *   CagdCrvStruct *:   Differentiated curve.                                 M
  383. *                                                                            *
  384. * KEYWORDS:                                                                  M
  385. *   BzrCrvDerive, derivatives                                                M
  386. *****************************************************************************/
  387. CagdCrvStruct *BzrCrvDerive(CagdCrvStruct *Crv)
  388. {
  389.     CagdBType
  390.     IsNotRational = !CAGD_IS_RATIONAL_CRV(Crv);
  391.     int i, j,
  392.     k = Crv -> Length,
  393.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  394.     CagdCrvStruct *DerivedCrv;
  395.  
  396.     if (!IsNotRational)
  397.     return BzrCrvDeriveRational(Crv);
  398.  
  399.     DerivedCrv = BzrCrvNew(MAX(1, k - 1), Crv -> PType);
  400.  
  401.     if (k >= 2) {
  402.     for (i = 0; i < k - 1; i++)
  403.         for (j = IsNotRational; j <= MaxCoord; j++)
  404.         DerivedCrv -> Points[j][i] =
  405.             (k - 1) * (Crv -> Points[j][i+1] - Crv -> Points[j][i]);
  406.     }
  407.     else {
  408.     for (j = IsNotRational; j <= MaxCoord; j++)
  409.         DerivedCrv -> Points[j][0] = 0.0;
  410.     }
  411.  
  412.     return DerivedCrv;
  413. }
  414.  
  415. /*****************************************************************************
  416. * DESCRIPTION:                                                               M
  417. * Returns a new Bezier curve, equal to the integral of the given Bezier      M
  418. * crv.                                                                     M
  419. * The given Bezier curve should be nonrational.                     M
  420. *                                         V
  421. *           n           n           n       n+1                 V
  422. *   /         /-           -      /       -   P    -                 V
  423. *  |        | \        n       \     |  n       \    i   \  n+1             V
  424. *  | C(t) = | / P  B (t) = / P   | B (t) = / -----  / B   (t) =             V
  425. * /        /  -     i  i       -  i /   i       - n + 1  -  j             V
  426. *            i=0          i=0             i=0     j=i+1                 V
  427. *                                         V
  428. *        n+1 j-1                                 V
  429. *         -   -                                     V
  430. *     1   \   \        n+1                                 V
  431. * = ----- /   / P  B   (t)                             V
  432. *   n + 1 -   -  i  j                                 V
  433. *        j=1 i=0                                 V
  434. *                                         V
  435. *                                         M
  436. *                                                                            *
  437. * PARAMETERS:                                                                M
  438. *   Crv:         Curve to integrate.                                         M
  439. *                                                                            *
  440. * RETURN VALUE:                                                              M
  441. *   CagdCrvStruct *:   Integrated curve.                                     M
  442. *                                                                            *
  443. * KEYWORDS:                                                                  M
  444. *   BzrCrvIntegrate, integrals                                               M
  445. *****************************************************************************/
  446. CagdCrvStruct *BzrCrvIntegrate(CagdCrvStruct *Crv)
  447. {
  448.     int i, j, k,
  449.     n = Crv -> Length,
  450.     MaxCoord = CAGD_NUM_OF_PT_COORD(Crv -> PType);
  451.     CagdCrvStruct *IntCrv;
  452.  
  453.     if (CAGD_IS_RATIONAL_CRV(Crv))
  454.     CAGD_FATAL_ERROR(CAGD_ERR_RATIONAL_NO_SUPPORT);
  455.  
  456.     IntCrv = BzrCrvNew(n + 1, Crv -> PType);
  457.  
  458.     for (k = 1; k <= MaxCoord; k++) {
  459.     CagdRType
  460.         *Points = Crv -> Points[k],
  461.         *IntPoints = IntCrv -> Points[k];
  462.  
  463.     for (j = 0; j < n + 1; j++) {
  464.         IntPoints[j] = 0.0;
  465.         for (i = 0; i < j; i++)
  466.             IntPoints[j] += Points[i];
  467.         IntPoints[j] /= n;
  468.     }
  469.     }
  470.  
  471.     return IntCrv;
  472. }
  473.  
  474. /*****************************************************************************
  475. * DESCRIPTION:                                                               M
  476. * Converts a Bezier curve into Bspline curve by adding an open knot vector.  M
  477. *                                                                            *
  478. * PARAMETERS:                                                                M
  479. *   Crv:     A Bezier curve to convert to a Bspline curve.                   M
  480. *                                                                            *
  481. * RETURN VALUE:                                                              M
  482. *   CagdCrvStruct *:   A Bspline curve representing Bezier curve Crv.        M
  483. *                                                                            *
  484. * KEYWORDS:                                                                  M
  485. *   CnvrtBezier2BsplineCrv, conversion                                       M
  486. *****************************************************************************/
  487. CagdCrvStruct *CnvrtBezier2BsplineCrv(CagdCrvStruct *Crv)
  488. {
  489.     CagdCrvStruct *BspCrv;
  490.  
  491.     if (Crv -> GType != CAGD_CBEZIER_TYPE) {
  492.     CAGD_FATAL_ERROR(CAGD_ERR_WRONG_CRV);
  493.     return NULL;
  494.     }
  495.  
  496.     BspCrv = CagdCrvCopy(Crv);
  497.  
  498.     BspCrv -> Order = BspCrv -> Length;
  499.     BspCrv -> KnotVector = BspKnotUniformOpen(BspCrv -> Length,
  500.                                BspCrv -> Order, NULL);
  501.     BspCrv -> GType = CAGD_CBSPLINE_TYPE;
  502.     return BspCrv;
  503. }
  504.  
  505. /*****************************************************************************
  506. * DESCRIPTION:                                                               M
  507. * Converts a Bspline curve into a set of Bezier curves by subdividing the    M
  508. * Bspline curve at all its internal knots.                     M
  509. *   Returned is a list of Bezier curves.                     M
  510. *                                                                            *
  511. * PARAMETERS:                                                                M
  512. *   Crv:     A Bspline curve to convert to a Bezier curve.                   M
  513. *                                                                            *
  514. * RETURN VALUE:                                                              M
  515. *   CagdCrvStruct *:   A list of Bezier curves representing the Bspline      M
  516. *                      curve Crv.                         M
  517. *                                                                            *
  518. * KEYWORDS:                                                                  M
  519. *   CnvrtBezier2BsplineCrv, conversion                                       M
  520. *****************************************************************************/
  521. CagdCrvStruct *CnvrtBspline2BezierCrv(CagdCrvStruct *Crv)
  522. {
  523.     CagdBType
  524.     NewCrv = FALSE;
  525.     int i, Order, Length;
  526.     CagdRType LastT, *KnotVector;
  527.     CagdCrvStruct *OrigCrv,
  528.     *BezierCrvs = NULL;
  529.  
  530.     if (Crv -> GType != CAGD_CBSPLINE_TYPE) {
  531.     CAGD_FATAL_ERROR(CAGD_ERR_WRONG_CRV);
  532.     return NULL;
  533.     }
  534.  
  535.     if (CAGD_IS_PERIODIC_CRV(Crv)) {
  536.         NewCrv = TRUE;
  537.         Crv = CnvrtPeriodic2FloatCrv(Crv);
  538.     }
  539.     if (CAGD_IS_BSPLINE_CRV(Crv) && !BspCrvHasOpenEC(Crv)) {
  540.     CagdCrvStruct
  541.         *TCrv = BspCrvOpenEnd(Crv);
  542.  
  543.     if (NewCrv)
  544.         CagdCrvFree(Crv);
  545.     Crv = TCrv;
  546.     NewCrv = TRUE;
  547.     }
  548.  
  549.     Order = Crv -> Order,
  550.     Length = Crv -> Length;
  551.     KnotVector = Crv -> KnotVector;
  552.     OrigCrv = Crv;
  553.  
  554.     for (i = Length - 1, LastT = KnotVector[Length]; i >= Order; i--) {
  555.         CagdRType
  556.             t = KnotVector[i];
  557.             
  558.     if (!APX_EQ(LastT, t)) {
  559.             CagdCrvStruct
  560.         *Crvs = BspCrvSubdivAtParam(Crv, t);
  561.  
  562.             if (Crv != OrigCrv)
  563.                 CagdCrvFree(Crv);
  564.  
  565.             Crvs -> Pnext -> Pnext = BezierCrvs;
  566.             BezierCrvs = Crvs -> Pnext;
  567.  
  568.             Crv = Crvs;
  569.             Crv -> Pnext = NULL;
  570.  
  571.         LastT = t;
  572.         }
  573.     }
  574.  
  575.     if (Crv == OrigCrv) {
  576.     /* No interior knots in this curve - just copy it: */
  577.     BezierCrvs = CagdCrvCopy(Crv);
  578.     }
  579.     else {
  580.         Crv -> Pnext = BezierCrvs;
  581.         BezierCrvs = Crv;
  582.     }
  583.  
  584.     for (Crv = BezierCrvs; Crv != NULL; Crv = Crv -> Pnext) {
  585.         Crv -> GType = CAGD_CBEZIER_TYPE;
  586.     Crv -> Length = Crv -> Order;
  587.     IritFree((VoidPtr) Crv -> KnotVector);
  588.     Crv -> KnotVector = NULL;
  589.     }
  590.  
  591.     if (NewCrv)
  592.     CagdCrvFree(Crv);
  593.  
  594.     return BezierCrvs;
  595. }
  596.